package stream;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 将流中对象进行聚合计算/分组操作
 */
public class StreamCollect {
    public static void main(String[] args) {
        collectToCollection();
        collectToArray();
        maxBy();
        minBy();
        sum();
        avg();
        group1();
        group2();
        group3();
        partition();
        join1();
        join2();
    }
    /**
     * 对流数据进行拼接，中间加拼接的字符，之后加上前缀和后缀
     */
    private static void join2() {
        String joinStr = Stream.of(new Student("Tom", 3, 60),
                new Student("Jerry", 2, 90),
                new Student("Tim", 1, 90),
                new Student("Jim", 5, 60))
                .map(Student::getName).collect(Collectors.joining(",","^","$"));
        System.out.println("joinStr = " + joinStr);
    }

    /**
     * 对流数据进行拼接，中间加拼接的字符
     */
    private static void join1() {
        String joinStr = Stream.of(new Student("Tom", 3, 60),
                new Student("Jerry", 2, 90),
                new Student("Tim", 1, 90),
                new Student("Jim", 5, 60))
                .map(Student::getName).collect(Collectors.joining(","));
        System.out.println("joinStr = " + joinStr);
    }

    /**
     * 分区，就是把数据分为两组，一组key为true，一组key为false
     */
    private static void partition() {
        Map<Boolean, List<Student>> collect = Stream.of(new Student("Tom", 3, 60),
                new Student("Jerry", 2, 90),
                new Student("Tim", 1, 90),
                new Student("Jim", 5, 60))
                .collect(Collectors.partitioningBy(s -> s.getScore()>60));
        collect.forEach((k, v) -> System.out.println("key:" + k + ",value:" + v));
    }

    /**
     * 简单分组
     */
    private static void group1() {
        Map<Integer, List<Student>> collect = Stream.of(new Student("Tom", 3, 60),
                new Student("Jerry", 2, 90),
                new Student("Tim", 1, 90),
                new Student("Jim", 5, 60))
                .collect(Collectors.groupingBy(Student::getScore));
        collect.forEach((k, v) -> System.out.println("key:" + k + ",value:" + v));// score为key
    }

    /**
     * 条件分组
     */
    private static void group2() {
        Map<String, List<Student>> collect = Stream.of(new Student("Tom", 3, 60),
                new Student("Jerry", 2, 90),
                new Student("Tim", 1, 90),
                new Student("Jim", 5, 60))
                .collect(Collectors.groupingBy(s -> {
                    if (s.getScore() >= 90) {
                        return "A"; // A将会是key
                    }
                    if (s.getScore() >= 60) {
                        return "C";
                    }
                    return "E";
                }));
        collect.forEach((k, v) -> System.out.println("key:" + k + ",value:" + v));
    }

    /**
     * 多级分组
     */
    private static void group3() {
        Map<Integer, Map<String, List<Student>>> collect = Stream.of(new Student("Tom", 3, 60),
                new Student("Jerry", 3, 90),
                new Student("Tim", 5, 90),
                new Student("Jim", 5, 60))
                .collect(Collectors.groupingBy(Student::getAge, Collectors.groupingBy(s -> {
                    if (s.getScore() >= 90) {
                        return "A";
                    }
                    if (s.getScore() >= 60) {
                        return "C";
                    }
                    return "E";
                })));
        collect.forEach((k, v) -> System.out.println("key:" + k + ",value:" + v));
    }

    private static void avg() {
        Double avg = Stream.of(new Student("Tom", 3, 60),
                new Student("Jerry", 2, 90),
                new Student("Tim", 1, 95))
                .collect(Collectors.averagingInt(Student::getScore));
        System.out.println("avg = " + avg);
    }

    private static void sum() {
        Integer sum = Stream.of(new Student("Tom", 3, 60),
                new Student("Jerry", 2, 90),
                new Student("Tim", 1, 95))
                .collect(Collectors.summingInt(s -> s.getScore()));
        System.out.println("sum = " + sum);
    }

    private static void minBy() {
        Optional<Student> collect = Stream.of(new Student("Tom", 3, 60),
                new Student("Jerry", 2, 90),
                new Student("Tim", 1, 95))
                .collect(Collectors.minBy((s1, s2) -> s1.getScore() - s2.getScore()));
        System.out.println("collect.get() = " + collect.get());
    }

    private static void maxBy() {
        Optional<Student> collect = Stream.of(new Student("Tom", 3, 60),
                new Student("Jerry", 2, 90),
                new Student("Tim", 1, 95))
                .collect(Collectors.maxBy((s1, s2) -> s1.getScore() - s2.getScore()));
        System.out.println("collect.get() = " + collect.get());
    }

    private static void collectToArray() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4);
//        Object[] objects = list.stream().toArray(); // 转成objects数组不方便
        Integer[] integers = list.stream().toArray(Integer[]::new); // 可以指定类型
    }

    private static void collectToCollection() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 1);
        List<Integer> collect = list.stream().collect(Collectors.toList());
//        Set<Integer> collect = list.stream().collect(Collectors.toSet()); //会自动去重
        System.out.println(collect);
    }
}

class Student {
    private String name;
    private Integer age;
    private Integer score;

    public Student(String name, Integer age, Integer score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getScore() {
        return score;
    }

    public void setScore(Integer score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", score=" + score +
                '}';
    }
}